#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         SelectionEditlet.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  This file defines the SelectionEditlet class, that is
#               used to generate single choice dropdowns for enumerated 
#               types
#
# See Also:     PropertyEditlet, PropertyRefleciton, 
#               PropertyDefinition, PropertyAccess 
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.Core import *
from Products.KnowledgeEngine.Editlet import Editlet
from Products.KnowledgeEngine.PropertyTypes import *
from Products.KnowledgeEngine.PropertyFormats import *
from Products.KnowledgeEngine.PropertyStructures import *

#####################################################################
## Zope Library Imports
# (none)
 
#####################################################################
## Python Library Imports
# (none)

#####################################################################
## SelectionEditlet Class Definition
class SelectionEditlet(Editlet):
    """
        An editlet for editing enumerated types
    """
    
    #---------------------------------------------------------------#

    def displayNameFor(self, value, possibleValues):
        """
            Returns the displayName for the specified value
            from the specified possible values.
        """
        
        for (displayName, displayValue) in possibleValues:
            if displayValue == value:
                return displayValue
               
        raise "Missing Value Exception", "SelectionEditlet can't locate display name for value %s in %s" % (value, possibleValues)
    
    #---------------------------------------------------------------#
    
    def isEditable(self, propertyDefinition, propertyAccess=None, value=None, isForConstructor=false, REQUEST=None, context=None):
        """
            Returns if the specified propertyDefinition can be
            edited by this editlet
        """

        return propertyDefinition.getStructure() == ps_ATOMIC and propertyDefinition.hasEnumeratedValues()
        
    #---------------------------------------------------------------#

    def generateEditorFor(self, propertyDefinition, propertyAccess=None, value=None, isForConstructor=false, REQUEST=None, context=None):
        """
            Returns a HTML editlet for the specified property.
        """

        #get the enumerated values [(DisplayName,Value)] from the property definition class (one must be provided)
        possibleValues = propertyDefinition.getEnumeratedValues(context)
                
        #the resulting editlet
        result = ""

        #-----------------
        #is the property read only?        
        if propertyDefinition.isReadPermitted() and not propertyDefinition.isWritePermitted():

            #get the value for the property
            if isForConstructor:
                value = propertyDefinition.getDefaultValue()
            else:
                value = propertyAccess.getPropertyValue(propertyDefinition.getIdentity())
            
            #create the editor
            result = "<table border=1><tr><td>%s</td></tr></table>" % (self.displayNameFor(value,possibleValues),)
        
        #-----------------
        #is the property writable?
        if propertyDefinition.isWritePermitted():
       
            #get the value for the property
            if propertyDefinition.isReadPermitted():
                if isForConstructor:
                    value = propertyDefinition.getDefaultValue()
                else:
                    #get the value for the property
                    value = propertyAccess.getPropertyValue(propertyDefinition.getIdentity())
            else:
                #not readable
                value = None
                
            #create the editor
            result += "<select id='ke%s' name='ke%s'>" % (propertyDefinition.getIdentity(), propertyDefinition.getIdentity())
            
            if propertyDefinition.hasArg('includeBlankOption') and propertyDefinition.getArg('includeBlankOption') == true:
                result += "<option value=\"\">Choose one:</option><option value=\"\">--</option>"
            
            for (displayName, displayValue) in possibleValues:
            
                if propertyDefinition.isReadPermitted() and ('%s' % displayValue) == ('%s' % value):
                    selected = " selected"
                else:
                    selected = ""                    

                #ensure our value doesn't get weirdly cast into a string!
                if propertyDefinition.getType() == pt_LONG or propertyDefinition.getType() == pt_INTEGER:
                    format = "%d"
                elif propertyDefinition.getType() == pt_FLOAT: 
                    format = "%f"
                else:          
                    format = "%s"
                    
                result += ("<option value='" + format + "'%s>%s</option>") % (displayValue, selected, displayName)
            
            result += "</select>"        
                                    
        return result
        
    #---------------------------------------------------------------#

    def updatePropertyWith(self, propertyDefinition, propertyAccess, REQUEST=None):
        """
            Attempts to update the specified property on the
            object implementing the PropertyAccess interface with the
            specified HTTP REQUEST.
        """

        #is write permitted on the specified property?
        if propertyDefinition.isWritePermitted():
        
            #get the value from the request
            value = REQUEST["ke%s" % (propertyDefinition.getIdentity(),)]
 
            #appropriately cast the value into either a long, integer or float if necessary
            try:
                if propertyDefinition.getType() == pt_LONG:
                    value = long(value)                
                elif propertyDefinition.getType() == pt_INTEGER:
                    value = int(value)
                elif propertyDefinition.getType() == pt_FLOAT: 
                    value = float(value)
            except ValueError:
                raise ValueError, ("A number was expected for the property '%s'" % propertyDefinition.getDisplayName())

            # Check we have a value if it isMandatory
            propertyDefinition.verifyMandatoryValue(value)
                
            #set the value for the property from the REQUEST
            propertyAccess.setPropertyValue(propertyDefinition.getIdentity(), value)
        
    #---------------------------------------------------------------#

#####################################################################
## Class Initialisation

# Register Editlet Information with the Knowledge Engine
registerEditlet("SelectionEditlet", SelectionEditlet())

#####################################################################
